using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;

using System.Windows.Media;
using Microsoft.TeamFoundation.WorkItemTracking.Client;

namespace TFSWorkflowControl.TeamExplorer.WPF
{
    public class StateInfoCollection : ObservableCollection<GroupInfo>
    {
        readonly Color[] STATE_COLOR_VALUES = null;
        readonly Color StartColor = Color.FromRgb(163, 243, 175);
        readonly Color EndColor = Color.FromRgb(40, 186, 62);
        private const string StateReferenceName = "System.State";
        private const string ReasonReferenceName = "System.Reason";
        private const string ChangedByReferenceName = "System.ChangedBy";
        
        private const string ChangedDateReferenceName = "System.ChangedDate";
        public StateInfoCollection()
        {

            STATE_COLOR_VALUES = new Color[] {                 
                Color.FromRgb(226,233,152),
                Color.FromRgb(186,218,235),
                Color.FromRgb(235,186,187),
            Color.FromRgb(204,241,160)};


            //StateInfo info;

            //info = new StateInfo() { Date = DateTime.Now.AddDays(-40), Name = "Active", Reason = "New", Who = "Tester" };

            //this.Add(info);
            //info = new StateInfo() { Date = DateTime.Now.AddDays(-17), Name = "Resolved", Reason = "Finished", Who = "Me" };
            //this.Add(info);
        }

        private GroupInfo GetLastGroupInfo()
        {
            if (this.Count == 0)
            {
                return null;
            }

            return this[this.Count - 1];
        }


        private static StateInfo CreateStateInfoFromRevision(Revision revision)
        {
            StateInfo result = new StateInfo();

            result.Date = (DateTime)revision.Fields[ChangedDateReferenceName].Value;
            result.Name = revision.Fields[StateReferenceName].Value.ToString();
            result.Who = revision.Fields[ChangedByReferenceName].Value.ToString();
            result.Reason = revision.Fields[ReasonReferenceName].Value.ToString();
            return result;
        }

        private static string GetValueInfoFromRevision(Revision revision, string referenceName)
        {
            return revision.Fields[referenceName].Value.ToString();
        }

        public Color GetColor(int position, int stateCount)
        {
            if (stateCount < 2)
            {
                return EndColor;
            }
            if (position >= stateCount || position < 0)
            {
                return EndColor;
            }

            int deltaR = EndColor.R - StartColor.R;
            int deltaG = EndColor.G - StartColor.G;
            int deltaB = EndColor.B - StartColor.B;


            return Color.FromRgb(
                (byte)(StartColor.R + (deltaR * position) / (stateCount - 1)),
                (byte)(StartColor.G + (deltaG * position) / (stateCount - 1)),
                (byte)(StartColor.B + (deltaB * position) / (stateCount - 1)));
        }


        public void FillFromWorkItem(WorkItem workItem, string referenceName)
        {


            var stateField = workItem.GetField(StateReferenceName);

            string[] stateValueArray = null;
            List<String> usedValues = new List<string>();
            int stateCount = 0;
            if (stateField != null)
            {
                stateValueArray = stateField.AllowedValues.Cast<string>().ToArray();
                stateCount = stateValueArray.Count();
            }

            var iterationColorDictionnary = new Dictionary<string, Color>();
            int color_index = 0;

            Clear();

            if (workItem == null)
            {
                return;
            }

            if (workItem.Revisions.Count == 0)
            {
                return;
            }
            string currentState = null;

            foreach (Revision revision in workItem.Revisions.OfType<Revision>())
            {
                var lastGroup = GetLastGroupInfo();
                string value = GetValueInfoFromRevision(revision, referenceName);
                string state = revision.Fields[StateReferenceName].Value.ToString();

                bool newIteration = lastGroup == null || lastGroup.GroupName != value;
                if (newIteration)
                {
                    lastGroup = new GroupInfo() { GroupName = value };

                    Color iterationColor;

                    if (!iterationColorDictionnary.TryGetValue(value, out iterationColor))
                    {
                        iterationColor = STATE_COLOR_VALUES[color_index];
                        iterationColorDictionnary.Add(value, iterationColor);
                        color_index = (color_index + 1) % STATE_COLOR_VALUES.Length;
                    }

                    lastGroup.Color = iterationColor;

                    this.Add(lastGroup);
                }

                if (state != currentState || newIteration)
                {
                    var stateInfo = CreateStateInfoFromRevision(revision);

                    if (stateValueArray != null)
                    {
                        int pos = -1;

                        for (int i = 0; i < usedValues.Count; i++)
                        {
                            if (stateInfo.Name == usedValues[i])
                            {
                                pos = i;
                                break;
                            }
                        }
                        if (pos == -1)
                        {
                            usedValues.Add(stateInfo.Name);
                            pos = usedValues.Count - 1;
                        }

                        stateInfo.Color = GetColor(pos, stateValueArray.Length);
                    }
                    else
                    {
                        stateInfo.Color = EndColor;
                    }

                    lastGroup.StateInfoList.Add(stateInfo);
                    currentState = state;
                }
            }
        }
    }
}
